package xyz.apiote.bimba.czwek.departures

import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.WindowCompat
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.coroutines.*
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.api.*
import xyz.apiote.bimba.czwek.databinding.ActivityDeparturesBinding
import xyz.apiote.bimba.czwek.repo.Departure
import xyz.apiote.bimba.czwek.repo.TrafficResponseException
import xyz.apiote.bimba.czwek.repo.OnlineRepository
import xyz.apiote.bimba.czwek.repo.Stop

class DeparturesActivity : AppCompatActivity() {
	private var _binding: ActivityDeparturesBinding? = null
	private val binding get() = _binding!!

	private lateinit var adapter: BimbaDeparturesAdapter

	private val handler = Handler(Looper.getMainLooper())
	private var runnable = Runnable {}

	private var openBottomSheet: DepartureBottomSheet? = null

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		_binding = ActivityDeparturesBinding.inflate(layoutInflater)
		setContentView(binding.root)

		binding.collapsingLayout.apply {
			title = getName()
			val tf = ResourcesCompat.getFont(this@DeparturesActivity, R.font.yellowcircle8)
			setCollapsedTitleTypeface(tf)
			setExpandedTitleTypeface(tf)
		}

		binding.departuresRecycler.layoutManager = LinearLayoutManager(this)
		adapter = BimbaDeparturesAdapter(layoutInflater, this, listOf()) {
			DepartureBottomSheet(it).apply {
				show(supportFragmentManager, DepartureBottomSheet.TAG)
				openBottomSheet = this
				setOnCancel { openBottomSheet = null }
			}
		}
		binding.departuresRecycler.adapter = adapter
		WindowCompat.setDecorFitsSystemWindows(window, false)
	}

	override fun onResume() {
		super.onResume()
		getDepartures()
	}

	override fun onPause() {
		super.onPause()
		handler.removeCallbacks(runnable)
	}

	private fun getName(): String {
		return when (intent?.action) {
			Intent.ACTION_VIEW -> getCode()
			null -> intent?.extras?.getString("name") ?: ""
			else -> ""
		}
	}

	private fun getCode(): String {
		@Suppress("SpellCheckingInspection") return when (intent?.action) {
			Intent.ACTION_VIEW -> {
				when (intent?.data?.host) {
					"www.peka.poznan.pl" -> intent?.data?.getQueryParameter("przystanek") ?: ""
					"rj.metropoliaztm.pl" -> intent?.data?.lastPathSegment ?: ""
					else -> ""
				}

			}

			null -> intent?.extras?.getString("code") ?: ""
			else -> ""
		}
	}

	private fun getFeedID(): String {
		return when (intent?.action) {
			Intent.ACTION_VIEW -> {
				return when (intent?.data?.host) {
					"www.peka.poznan.pl" -> "poznan_ztm"
					"rj.metropoliaztm.pl" -> "gzm_ztm"
					else -> ""
				}
			}

			null -> {
				intent?.extras?.getString("feedID") ?: ""
			}

			else -> ""
		}
	}

	private fun getLine(): String? {
		return when (intent?.action) {
			null -> intent?.extras?.getString("line")
			else -> null
		}
	}

	private fun getDepartures() {
		val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
		MainScope().launch {
			try {
				val repository = OnlineRepository()
				val stopDepartures =
					repository.getDepartures(cm, getFeedID(), getCode(), getLine(), this@DeparturesActivity)
				updateItems(stopDepartures!!.departures, stopDepartures.stop)
				openBottomSheet?.departureID()?.let { adapter.get(it) }?.let { openBottomSheet?.update(it) }
			} catch (e: TrafficResponseException) {
				showError(e.error)
				Log.w("Departures", "$e")
			}
		}
		handler.removeCallbacks(runnable)
		runnable = Runnable { getDepartures() }
		handler.postDelayed(runnable, 30 * 1000)
	}

	private fun showError(error: Error) {
		binding.departuresProgress.visibility = View.GONE
		binding.departuresRecycler.visibility = View.GONE
		binding.errorImage.visibility = View.VISIBLE
		binding.errorText.visibility = View.VISIBLE

		binding.errorText.text = getString(error.stringResource)
		binding.errorImage.setImageDrawable(AppCompatResources.getDrawable(this, error.imageResource))
	}

	private fun updateItems(departures: List<Departure>, stop: Stop) {
		binding.departuresProgress.visibility = View.GONE
		adapter.update(departures)
		binding.collapsingLayout.apply {
			title = stop.name
		}
		if (departures.isEmpty()) {
			binding.errorImage.visibility = View.VISIBLE
			binding.errorText.visibility = View.VISIBLE
			binding.departuresRecycler.visibility = View.GONE

			binding.errorText.text = getString(R.string.no_departures)
			binding.errorImage.setImageDrawable(
				AppCompatResources.getDrawable(
					this, R.drawable.error_search
				)
			)
		} else {
			binding.departuresOverlay.visibility = View.GONE
			binding.errorImage.visibility = View.GONE
			binding.errorText.visibility = View.GONE
			binding.departuresRecycler.visibility = View.VISIBLE
		}
		// todo [3.2; traffic] alerts
		// todo [3.2; traffic] stop info
	}
}